package com.mlethe.library.keyboard;

import android.app.Activity;
import android.content.Context;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.os.Build;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowInsets;
import android.view.WindowInsetsController;
import android.widget.EditText;
import android.widget.PopupWindow;

import androidx.annotation.CallSuper;

import java.util.ArrayList;
import java.util.List;

/**
 * 自定义键盘弹窗
 *
 * @author Mlethe
 */
public abstract class KeyboardWindow {

    private Context mContext;

    private PopupWindow mPopupWindow;

    private ViewGroup mDecorView;

    private KeyboardView mKeyboardView;

    private EditText mEditText;

    private int mAnimationStyle = R.style.keyboard_anim;

    private boolean mOutsideTouchable = true;

    /**
     * 虚拟导航是否隐藏
     */
    private boolean mNavigationHide = false;

    private final OnPopupWindowDismissListener mDismissListener = new OnPopupWindowDismissListener();

    private final List<View> mOnTouchInterceptorViews = new ArrayList<>();

    public KeyboardWindow(Activity activity) {
        this((ViewGroup) activity.getWindow().getDecorView());
    }

    public KeyboardWindow(ViewGroup viewGroup) {
        mDecorView = viewGroup;
        mContext = mDecorView.getContext();
        View view = LayoutInflater.from(mContext).inflate(getLayout(), null);
        mKeyboardView = view.findViewById(getKeyboardId());
        if (mKeyboardView == null) {
            throw new RuntimeException("KeyboardView is not find!");
        }
        onViewCreated(view);
        mKeyboardView.setPreviewEnabled(false);
        mPopupWindow = new PopupWindow(view, ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
        onCreated(mPopupWindow);
        // 设置popupwindow外部可点击
        mPopupWindow.setOutsideTouchable(mOutsideTouchable);
        mPopupWindow.setOnDismissListener(mDismissListener);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP_MR1) {
            mPopupWindow.setAttachedInDecor(true);
        }
        mPopupWindow.setAnimationStyle(mAnimationStyle);
        // 解决setTouchInterceptor事件无法捕获
        mPopupWindow.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
        mPopupWindow.setTouchInterceptor(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                if (event.getAction() == MotionEvent.ACTION_OUTSIDE) {
                    if (isClickEditText(event) || isTouchInterceptor(event)) {
                        return true;
                    }
                }
                return false;
            }
        });
    }

    /**
     * 是否拦截事件
     *
     * @return
     */
    private boolean isTouchInterceptor(MotionEvent event) {
        for (View view : mOnTouchInterceptorViews) {
            if (isTouchView(view, event)) {
                return true;
            }
        }
        return false;
    }

    /**
     * 获取布局
     *
     * @return
     */
    protected abstract int getLayout();

    /**
     * view 创建完成
     *
     * @return view
     */
    protected void onViewCreated(View view) {
    }

    /**
     * 获取键盘 View id
     *
     * @return
     */
    protected abstract int getKeyboardId();

    /**
     * PopupWindow 创建完成
     *
     * @param popupWindow
     */
    protected void onCreated(PopupWindow popupWindow) {
    }

    /**
     * 获取键盘
     *
     * @return
     */
    protected abstract Keyboard[] getKeyboards();

    public Context getContext() {
        return mContext;
    }

    /**
     * 获取 KeyboardView
     *
     * @return
     */
    public KeyboardView getKeyboardView() {
        return mKeyboardView;
    }

    /**
     * 获取 EditText
     *
     * @return
     */
    public EditText getEditText() {
        return mKeyboardView.getEditText();
    }

    /**
     * 设置 EditText
     *
     * @param editText
     * @return
     */
    public KeyboardWindow setEditText(EditText editText) {
        this.mEditText = editText;
        return this;
    }

    /**
     * 设置动画
     *
     * @param animationStyle
     * @return
     */
    public KeyboardWindow setAnimationStyle(int animationStyle) {
        if (mAnimationStyle == animationStyle) {
            return this;
        }
        mAnimationStyle = animationStyle;
        if (mPopupWindow != null) {
            mPopupWindow.setAnimationStyle(mAnimationStyle);
        }
        return this;
    }

    /**
     * 设置popupwindow外部可点击
     *
     * @param touchable
     * @return
     */
    public KeyboardWindow setOutsideTouchable(boolean touchable) {
        if (mOutsideTouchable == touchable) {
            return this;
        }
        mOutsideTouchable = touchable;
        if (mPopupWindow != null) {
            mPopupWindow.setOutsideTouchable(mOutsideTouchable);
        }
        return this;
    }

    /**
     * 设置虚拟导航是否隐藏
     *
     * @param hide true 隐藏，false 显示
     * @return
     */
    public KeyboardWindow setNavigationHide(boolean hide) {
        this.mNavigationHide = hide;
        return this;
    }

    /**
     * 设置弹窗关闭监听事件
     *
     * @param onDismissListener
     * @return
     */
    public KeyboardWindow setOnDismissListener(PopupWindow.OnDismissListener onDismissListener) {
        mDismissListener.setOnDismissListener(onDismissListener);
        return this;
    }

    /**
     * 添加 popupwindow 外部点击事件拦截的 view
     *
     * @param views
     * @return
     */
    public KeyboardWindow addTouchInterceptorView(View... views) {
        if (views != null) {
            for (View view : views) {
                if (view != null && !mOnTouchInterceptorViews.contains(view)) {
                    this.mOnTouchInterceptorViews.add(view);
                }
            }
        }
        return this;
    }

    /**
     * 删除 popupwindow 外部点击事件拦截的 view
     *
     * @param views
     * @return
     */
    public KeyboardWindow removeTouchInterceptorView(View... views) {
        if (views != null) {
            for (View view : views) {
                if (view != null) {
                    this.mOnTouchInterceptorViews.remove(view);
                }
            }
        }
        return this;
    }

    /**
     * 清除 popupwindow 外部点击事件拦截的 view
     *
     * @return
     */
    public KeyboardWindow clearTouchInterceptorView() {
        mOnTouchInterceptorViews.clear();
        return this;
    }

    /**
     * 是否是点击的 EditText
     *
     * @param event
     * @return
     */
    public boolean isClickEditText(MotionEvent event) {
        if (mKeyboardView != null) {
            EditText editText = mKeyboardView.getEditText();
            return isTouchView(editText, event);
        }
        return false;
    }

    /**
     * 是否触摸到 view
     *
     * @param view
     * @param event
     * @return
     */
    public boolean isTouchView(View view, MotionEvent event) {
        if (view != null) {
            int[] location = new int[2];
            view.getLocationOnScreen(location);
            float x = event.getRawX();
            float y = event.getRawY();
            int left = location[0];
            int right = left + view.getMeasuredWidth();
            int top = location[1];
            int bottom = top + view.getMeasuredHeight();
            if (x >= left && x <= right && y >= top && y <= bottom) {
                return true;
            }
        }
        return false;
    }

    /**
     * 是否显示
     *
     * @return
     */
    public boolean isShowing() {
        return mPopupWindow != null && mPopupWindow.isShowing();
    }

    /**
     * 显示软键盘
     */
    public void show() {
        mKeyboardView.setKeyboards(getKeyboards());
        mKeyboardView.showKeyboard(mEditText);
        if (mPopupWindow != null && !mPopupWindow.isShowing()) {
            mPopupWindow.showAtLocation(mDecorView, Gravity.BOTTOM, 0, 0);
            if (!mNavigationHide) {
                return;
            }
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
                WindowInsetsController windowInsetsController = mPopupWindow.getContentView().getWindowInsetsController();
                if (windowInsetsController != null) {
                    windowInsetsController.hide(WindowInsets.Type.navigationBars());
                }
            } else {
                int flag = View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
                        | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_FULLSCREEN;
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
                    flag |= View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
                }
                mPopupWindow.getContentView().setSystemUiVisibility(flag);
            }
            mPopupWindow.update();
        }
    }

    /**
     * 关闭软键盘
     */
    public void dismiss() {
        if (isShowing()) {
            mKeyboardView.hiddenKeyboard();
            mPopupWindow.dismiss();
        }
    }

    /**
     * 销毁
     */
    @CallSuper
    public void destroy() {
        mOnTouchInterceptorViews.clear();
        mContext = null;
        mPopupWindow = null;
        mDecorView = null;
        mKeyboardView = null;
        mDismissListener.listener = null;
    }

    /**
     * 关闭回调
     */
    protected void onDismiss() {
    }

    private class OnPopupWindowDismissListener implements PopupWindow.OnDismissListener {

        private PopupWindow.OnDismissListener listener;

        public void setOnDismissListener(PopupWindow.OnDismissListener listener) {
            this.listener = listener;
        }

        @Override
        public void onDismiss() {
            KeyboardWindow.this.onDismiss();
            if (listener != null) {
                listener.onDismiss();
            }
        }
    }

}
